#include "SocketTCP.hpp"
#include <iostream>

#pragma comment(lib, "ws2_32.lib")

namespace vrts
{
    bool SocketTCP::m_socketInited = false;
    SocketTCP::SocketTCP()
    {
        // init lib
        WSAData wsaData;
        int ret = WSAStartup(WINSOCK_VERSION, &wsaData);
        if(ret == SOCKET_ERROR)
        {
            std::cout << "Wsastartup error!" << WSAGetLastError() << std::endl;
            return;
        }

        m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);

    }
    
    SocketTCP::~SocketTCP()
    {
        closesocket(m_socket);
        WSACleanup();
    }
    
    bool SocketTCP::Bind(unsigned short port, char * hostIp)
    {
        sockaddr_in name;
        name.sin_family = AF_INET;
        name.sin_addr.s_addr = hostIp == NULL?INADDR_ANY :inet_addr(hostIp);
        name.sin_port = htons(port);
        auto ret = bind(m_socket, (sockaddr*)&name, sizeof(sockaddr_in));

        ret = listen(m_socket, 5);
        return ret  != SOCKET_ERROR;
    }
    
    SOCKET SocketTCP::Accept()
    {
        sockaddr_in clientAddr;
        int addrLen = sizeof(sockaddr_in);
        SOCKET s = accept(m_socket, (sockaddr*)&clientAddr, &addrLen);
        m_clients[s] = clientAddr;
        std::cout << "Accept a connetion from:" << inet_ntoa(clientAddr.sin_addr) << ":" << ntohs(clientAddr.sin_port) << std::endl;
        return s;
    }
    
    int SocketTCP::Connect(unsigned short port, char * hostIp)
    {
        sockaddr_in name;
        name.sin_family = AF_INET;
        name.sin_addr.s_addr = hostIp == NULL?INADDR_ANY :inet_addr(hostIp);
        name.sin_port = htons(port);
        auto ret = connect(m_socket, (sockaddr*)&name, sizeof(sockaddr));
        return ret;
    }
    
    int SocketTCP::SendData(char * buf, int bufLen)
    {
        int toLen = sizeof(sockaddr);
        int sendLen = 0;
        for(auto c: m_clients)
        {
            sendLen = sendto(c.first, buf, bufLen, 0, (sockaddr*)&c.second,toLen);
        }
        return sendLen;
    }
    
    int SocketTCP::ReceiveData(char *buf, int &bufLen)
    {
         for(auto c: m_clients)
        {
            bufLen =  recv(c.first, buf, bufLen, 0);
        }
       return bufLen;
    }

}